package ua.kpi_java_training.tyshchenko.module2;

/**
 * Class's behavior of movement in six directions
 *
 * @author Vlad Tyshchenko
 * @version 13 June 2013
 */
public class MovementInSixDirections extends MovementBehavior {
    final int AMOUNT_DIRECTION = 6;

    public MovementInSixDirections(Position position) {
        super(position);
    }

    /**
     * Method get random number [0, 5] and chooses directions of movement of fish
     * If number is 0 - up - left;
     * If number is 1 - up - right;
     * If number is 2 - right;
     * If number is 3 - down - right;
     * If number is 4 - down - left;
     * If number is 5 - left;
     *
     * @param lengthStep the amount of steps per cycle
     */
    void move(int lengthStep) {
        AbstractRand rand = new RandomNumber();
        boolean checkMove = false;
        do {
            int direction = rand.getDirection(AMOUNT_DIRECTION);
            if (direction == 0) {
                checkMove = upLeft(lengthStep);
            } else if (direction == 1) {
                checkMove = upRight(lengthStep);
            } else if (direction == 2) {
                checkMove = right(lengthStep);
            } else if (direction == 3) {
                checkMove = downRight(lengthStep);
            } else if (direction == 4) {
                checkMove = downLeft(lengthStep);
            } else if (direction == 5) {
                checkMove = left(lengthStep);
            }
        } while (!checkMove);
    }

    /**
     * Mock object
     */
    public void move(AbstractRand rand, int lengthStep) {
        boolean checkMove = false;
        do {
            int direction = rand.getDirection(AMOUNT_DIRECTION);
            if (direction == 0) {
                checkMove = upLeft(lengthStep);
            } else if (direction == 1) {
                checkMove = upRight(lengthStep);
            } else if (direction == 2) {
                checkMove = right(lengthStep);
            } else if (direction == 3) {
                checkMove = downRight(lengthStep);
            } else if (direction == 4) {
                checkMove = downLeft(lengthStep);
            } else if (direction == 5) {
                checkMove = left(lengthStep);
            }
        } while (!checkMove);
    }

    private boolean upLeft(int lengthStep) {
        boolean checkMove;
        Position clonePosition = position.clone();
        for (int i = 0; i < lengthStep; i++) {
            clonePosition = position.clone();
            if (position.getLength() % 2 == 0) {
                checkMove = position.robCoordinateX(1) & position.robCoordinateY(1);
                position = checkMove(clonePosition, !checkMove);
            } else {
                position.robCoordinateY(1);
            }
            position = checkMove(clonePosition, position.checkHurdle());
        }
        return !position.equals(clonePosition);
    }

    private boolean upRight(int lengthStep) {
        boolean checkMove;
        Position clonePosition = position.clone();
        for (int i = 0; i < lengthStep; i++) {
            clonePosition = position.clone();
            if (position.getLength() % 2 == 0) {
                position.robCoordinateY(1);
            } else {
                checkMove = position.robCoordinateY(1) & position.addCoordinateX(1);
                position = checkMove(clonePosition, !checkMove);
            }
            position = checkMove(clonePosition, position.checkHurdle());
        }
        return !position.equals(clonePosition);
    }

    private boolean downRight(int lengthStep) {
        boolean checkMove;
        Position clonePosition = position.clone();
        for (int i = 0; i < lengthStep; i++) {
            clonePosition = position.clone();
            if (position.getLength() % 2 == 0) {
                position.addCoordinateY(1);
            } else {
                checkMove = position.addCoordinateY(1) & position.addCoordinateX(1);
                position = checkMove(clonePosition, !checkMove);
            }
            position = checkMove(clonePosition, position.checkHurdle());
        }
        return !position.equals(clonePosition);
    }

    private boolean downLeft(int lengthStep) {
        boolean checkMove;
        Position clonePosition = position.clone();
        for (int i = 0; i < lengthStep; i++) {
            clonePosition = position.clone();
            if (position.getLength() % 2 == 0) {
                checkMove = position.robCoordinateX(1) & position.addCoordinateY(1);
                position = checkMove(clonePosition, !checkMove);
            } else {
                position.addCoordinateY(1);
            }
            position = checkMove(clonePosition, position.checkHurdle());
        }
        return !position.equals(clonePosition);
    }

    private boolean left(int lengthStep) {
        return position.robCoordinateX(lengthStep);
    }

    private boolean right(int lengthStep) {
        return position.addCoordinateX(lengthStep);
    }

    /**
     * Method checks changing move
     *
     * @param clonePosition
     * @param checkMove     false - if done wrong move
     * @return
     */
    private Position checkMove(Position clonePosition, boolean checkMove) {
        if (checkMove) {
            return clonePosition;
        }
        return position;
    }


}
